package cn.iocoder.yudao.framework.business.basic.dao.repository;

import cn.iocoder.yudao.framework.common.exception.ServiceException;
import jakarta.annotation.Resource;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Repository;

import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

/**
 * 分布式锁 Redis DAO。另外也可用 {@code https://gitee.com/baomidou/lock4j}
 * 单机锁可使用 {@link java.util.concurrent.locks.ReentrantLock}
 *
 * @author 芋道源码
 */
@Repository
public class LockRedisRepository {
    @Resource
    private RedissonClient redissonClient;

    public <V> V lock(String key, Long timeoutMillis, Callable<V> callable) {
        RLock lock = redissonClient.getLock(key);
        try {
            lock.lock(timeoutMillis, TimeUnit.MILLISECONDS);
            // 执行逻辑
            return callable.call();
        } catch (Throwable e) {
            if (e instanceof ServiceException exception) {
                throw exception;
            }
            throw new RuntimeException(e);
        } finally {
            lock.unlock();
        }
    }

}
